﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using SWS = System.Web.Security;
using SNM = System.Net.Mail;
using SSP = System.Security.Principal;
using MIC = Microsoft.IdentityModel.Claims;
#if USE_WIF
using CCM = CodeCamp.Models;
#endif
using CodeCamp.Infrastructure;
using CodeCamp.Infrastructure.Extensions;
using CodeCamp.Models.Shared;
using CodeCamp.Model;
using RGoodSW.Logger.MvcHelper.Models;
using RGoodSW.Logger.Interfaces;

namespace CodeCamp.Controllers
{
    public class ControllerBase : Controller
    {
        internal static class TempDataKeys
        {
            internal const string ErrorMessage = "ErrorMessage";
        }

        private string _defaultEventShortName;

        protected ControllerBase(ILoggerExtended logger)
        {
            if (logger == null)
                throw new ArgumentNullException("logger");
            this.Logger = logger;
            this.DefaultValueProvider = null;
        }

        protected ControllerBase(IDefaultValueProvider defaultValueProvider, ILoggerExtended logger)
            : this(logger)
        {
            if (defaultValueProvider == null)
                throw new ArgumentNullException("defaultValueProvider");
            this.DefaultValueProvider = defaultValueProvider;
        }

        protected IDefaultValueProvider DefaultValueProvider { get; private set; }
        protected ILoggerExtended Logger { get; private set; }
        internal ILoggerExtended GetLogger() { return Logger; }
        protected static readonly DateTime MinSqlTime = new DateTime(1753, 1, 1);
        protected Nullable<int> SiteUserId { get; private set; }

        protected DateTime FixupDateTimeForSqlMin(DateTime inputDateTime)
        {
            if (inputDateTime < MinSqlTime)
                return MinSqlTime;
            return inputDateTime;
        }

        protected string DefaultEventShortName
        {
            get
            {
                if (_defaultEventShortName == null)
                {
                    _defaultEventShortName = DefaultValueProvider.GetDefaultStringValue(Constants.Tags.defaultEventShortName, Constants.Defaults.defaultEventShortName);
                }
                return _defaultEventShortName;
            }
        }

        private string _defaultPresenterReplyEmailAddress;
        protected string DefaultPresenterReplyEmailAddress
        {
            get
            {
                if (string.IsNullOrWhiteSpace(_defaultPresenterReplyEmailAddress))
                {
                    if (DefaultValueProvider != null)
                    {
                        _defaultPresenterReplyEmailAddress = DefaultValueProvider.GetStringValueOrNull(Constants.Tags.defaultPresenterReplyEmailAddress);
                    }
                }
                return _defaultPresenterReplyEmailAddress;
            }
        }

        private string _defaultEmailFromAddress;
        protected string DefaultEmailFromAddress
        {
            get
            {
                if (string.IsNullOrWhiteSpace(_defaultEmailFromAddress))
                {
                    if (string.IsNullOrWhiteSpace(_defaultEmailFromAddress))
                    {
                        _defaultEmailFromAddress = DefaultValueProvider.GetStringValueOrNull(Constants.Tags.defaultEmailFromAddress);
                    }
                }
                return _defaultEmailFromAddress;
            }
        }


        //************
        #region Logger

        protected void LogException(string controllerAndAction, Exception ex)
        {
            string errorMsg = null;
            if (TempData.ContainsKey(TempDataKeys.ErrorMessage))
                errorMsg = TempData[TempDataKeys.ErrorMessage] as string;

            if (ex.GetType() == typeof(System.Data.Entity.Validation.DbEntityValidationException))
            {
                System.Data.Entity.Validation.DbEntityValidationException ex2 = ex as System.Data.Entity.Validation.DbEntityValidationException;
                if (ex2 != null)
                {
                    LogException(controllerAndAction, ex2);
                    return;
                }
            }
            if (ex.GetType() == typeof(System.Data.Entity.Infrastructure.DbUpdateException))
            {
                System.Data.Entity.Infrastructure.DbUpdateException ex2 = ex as System.Data.Entity.Infrastructure.DbUpdateException;
                if (ex2 != null)
                {
                    LogException(controllerAndAction, ex2);
                    return;
                }
            }
            StringBuilder logMsg = new StringBuilder();
            if (!string.IsNullOrWhiteSpace(errorMsg))
            {
                logMsg.AppendFormat("{1} {0}",
                    Environment.NewLine,
                    errorMsg);
            }
            logMsg.AppendFormat("{1} | {2}: {3} {0}",
                Environment.NewLine,
                controllerAndAction,
                ex.GetType(),
                ex.Message);
            if ((this.User != null) && (this.User.Identity != null) && this.User.Identity.IsAuthenticated)
            {
                logMsg.AppendFormat("User = \"{1}\" {0}",
                    Environment.NewLine,
                    this.User.Identity.Name
                    );
            }
            Logger.Error(logMsg.ToString(), ex);
        }


        protected void LogException(string controllerAndAction, System.Data.Entity.Infrastructure.DbUpdateException ex)
        {
            StringBuilder logMsg = new StringBuilder();
            logMsg.AppendFormat("{1} | {2}: {3} {0}",
                Environment.NewLine,
                controllerAndAction,
                ex.GetType(),
                ex.Message);
            if ((this.User != null) && (this.User.Identity != null) && this.User.Identity.IsAuthenticated)
            {
                logMsg.AppendFormat("User = \"{1}\" {0}",
                    Environment.NewLine,
                    this.User.Identity.Name
                    );
            }
            if (ex.InnerException != null)
            {
                Exception ex2 = ex.InnerException;
                while (ex2 != null)
                {
                    logMsg.AppendFormat("{1}: {2} {0}",
                        Environment.NewLine,
                        ex2.GetType(),
                        ex2.Message);
                    ex2 = ex2.InnerException;
                }
            }
            Logger.Error(logMsg.ToString(), ex);
        }

        protected void LogException(string controllerAndAction, System.Data.Entity.Validation.DbEntityValidationException ex)
        {
            StringBuilder logMsg = new StringBuilder();
            logMsg.AppendFormat("{1} | {2}: {3} {0}",
                Environment.NewLine,
                controllerAndAction,
                ex.GetType(),
                ex.Message);
            if ((this.User != null) && (this.User.Identity != null) && this.User.Identity.IsAuthenticated)
            {
                logMsg.AppendFormat("User = \"{1}\" {0}",
                    Environment.NewLine,
                    this.User.Identity.Name
                    );
            }
            if (ex.EntityValidationErrors != null)
            {
                logMsg.AppendLine("\t-----");
                foreach (System.Data.Entity.Validation.DbEntityValidationResult result in ex.EntityValidationErrors)
                {
                    logMsg.AppendFormat("\t{1} {0}",
                        Environment.NewLine,
                        result.Entry);
                    if (result.ValidationErrors != null)
                    {
                        foreach (System.Data.Entity.Validation.DbValidationError error in result.ValidationErrors)
                        {
                            logMsg.AppendFormat("\t\t{1}: {2} {0}",
                                Environment.NewLine,
                                error.PropertyName,
                                error.ErrorMessage);
                        }
                    }
                }
            }
            Logger.Error(logMsg.ToString(), ex);
        }

        protected void SetLoggerThreadContextData()
        {
            Logger.SetThreadContextData(new LogContextData(this.User, this.Request));
        }

        protected void SetLoggerThreadContextData(ExceptionContext filterContext)
        {
            SSP.IPrincipal principal = null;
            if ((filterContext.RequestContext != null) && (filterContext.RequestContext.HttpContext != null))
            {
                principal = filterContext.RequestContext.HttpContext.User;
                Logger.SetThreadContextData(new LogContextData(principal, filterContext.RequestContext.HttpContext.Request));
            }
            else
            {
                Logger.SetThreadContextData(new LogContextData(this.User, this.Request));
            }
        }

        protected void SetLoggerThreadContextData(SiteUser siteUser)
        {
            LogContextData context = null;

            if ((siteUser != null) &&
                (!UserIsAuthenticated(this.User) || string.IsNullOrWhiteSpace(this.User.Identity.Name)))
            {
                string userName = string.Concat(
                                    string.Concat(siteUser.FirstName, " ", siteUser.LastName).TruncateWithElipses(80),
                                    " ",
                                    siteUser.Id.ToString());
                context = new LogContextData(userName, this.Request);
            }
            else
            {
                context = new LogContextData(this.User, this.Request);
            }
            Logger.SetThreadContextData(context);
        }

        protected override void OnException(ExceptionContext filterContext)
        {
            try
            {
                if (this.Logger != null)
                {
                    SetLoggerThreadContextData(filterContext);
                    string currentController = null;
                    string currentAction = null;
                    if (filterContext.RouteData != null)
                    {
                        currentController = filterContext.RouteData.Values["controller"] as string;
                        currentAction = filterContext.RouteData.Values["action"] as string;
                    }
                    LogException(string.Format("{0}/{1}", currentController, currentAction),
                        filterContext.Exception);
                }
            }
            catch
#if DEBUG
 (Exception ex)
            {
                int foo = 1;
            }
#else
        {}
#endif
            if (filterContext.Exception is System.Data.SqlClient.SqlException)
            {
            }
            else
            {
            }
            base.OnException(filterContext);
        }

        #endregion //Logger


        //****************
        #region ClaimsAuth
        internal static List<MIC.Claim> GetClaimsOfType(MIC.ClaimCollection claims, string claimType)
        {
            List<MIC.Claim> claimList = new List<MIC.Claim>();

            foreach (MIC.Claim claim in claims)
            {
                if (claim.ClaimType == claimType)
                    claimList.Add(claim);
            }
            return claimList;
        }

        internal static MIC.Claim GetFirstClaim(MIC.ClaimCollection claims, string claimType, out int claimCount)
        {
            List<MIC.Claim> claimList = GetClaimsOfType(claims, claimType);
            claimCount = claimList.Count;
            if (claimList.Count > 0)
                return claimList[0];
            return null;
        }

        internal static MIC.Claim GetFirstClaim(SSP.IPrincipal principal, string claimType, out int claimCount)
        {
            claimCount = 0;
            MIC.ClaimsPrincipal claimsPrincipal = principal as MIC.ClaimsPrincipal;
            if (claimsPrincipal != null)
            {
                MIC.ClaimsIdentity claimsIdent = claimsPrincipal.Identity as MIC.ClaimsIdentity;
                if (claimsIdent != null)
                {
                    List<MIC.Claim> claimList = GetClaimsOfType(claimsIdent.Claims, claimType);
                    claimCount = claimList.Count;
                    if (claimList.Count > 0)
                        return claimList[0];
                }
            }
            return null;
        }

        internal static string GetFirstClaimValue(SSP.IPrincipal principal, string claimType)
        {
            int claimCount;
            return GetFirstClaimValue(principal, claimType, out claimCount);
        }

        internal static string GetFirstClaimValue(SSP.IPrincipal principal, string claimType, out int claimCount)
        {
            MIC.Claim claim = GetFirstClaim(principal, claimType, out claimCount);
            if (claim != null)
                return claim.Value;
            return null;
        }

        internal static void GetNameClaim(SSP.IPrincipal principal, string claimType, out int claimCount,
            out string firstName, out string lastName)
        {
            firstName = null;
            lastName = null;
            string nameClaim = GetFirstClaimValue(principal, claimType, out claimCount);
            if (!string.IsNullOrWhiteSpace(nameClaim))
            {
                int lastSpaceIdx = nameClaim.LastIndexOf(' ');
                if (lastSpaceIdx <= 0)
                {
                    firstName = nameClaim.Trim();
                    lastName = "?";
                }
                else
                {
                    firstName = nameClaim.Substring(0, lastSpaceIdx).Trim();
                    lastName = nameClaim.Substring(lastSpaceIdx).Trim();
                }
            }
        }
#if USE_WIF

        protected bool UserMatchesSiteUser(SSP.IPrincipal principal, SiteUser siteUser)
        {
            if (UserIsAuthenticated(principal) && (siteUser != null) && (siteUser.Id != 0))
            {
                int claimCount;
                MIC.Claim providerClaim = GetFirstClaim(principal, CodeCampDataRepository.ClaimTypes.identityprovider_2010, out claimCount);
                MIC.Claim identityClaim = GetFirstClaim(principal, CodeCampDataRepository.ClaimTypes.nameidentifier_2005, out claimCount);
                if ((providerClaim != null) && (identityClaim != null))
                {
                    string identityProvider = providerClaim.Value;
                    string originalClaimIssuer = identityClaim.OriginalIssuer;
                    string claimType = identityClaim.ClaimType;
                    string claim = identityClaim.Value;
                    if (!string.IsNullOrWhiteSpace(identityProvider) && !string.IsNullOrWhiteSpace(claimType)
                        && !string.IsNullOrWhiteSpace(claim))
                    {
                        if (identityProvider.Equals(siteUser.UserIdentityProvider, StringComparison.InvariantCultureIgnoreCase)
                            && claimType.Equals(siteUser.UserIdentityClaimType, StringComparison.InvariantCultureIgnoreCase)
                            && claim.Equals(siteUser.UserIdentityClaim, StringComparison.InvariantCultureIgnoreCase))
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        protected Presenter GetSessionPresenterMatchingUser(SSP.IPrincipal principal, Session session)
        {
            Presenter sessionPresenterMatchingUser = null;
            if (UserIsAuthenticated(principal) && (session != null) && (session.Id != 0))
            {
                int claimCount;
                MIC.Claim providerClaim = GetFirstClaim(principal, CodeCampDataRepository.ClaimTypes.identityprovider_2010, out claimCount);
                MIC.Claim identityClaim = GetFirstClaim(principal, CodeCampDataRepository.ClaimTypes.nameidentifier_2005, out claimCount);
                if ((providerClaim != null) && (identityClaim != null))
                {
                    string identityProvider = providerClaim.Value;
                    string claimType = identityClaim.ClaimType;
                    string claim = identityClaim.Value;
                    if (!string.IsNullOrWhiteSpace(identityProvider) && !string.IsNullOrWhiteSpace(claimType)
                        && !string.IsNullOrWhiteSpace(claim))
                    {
                        sessionPresenterMatchingUser =
                            (
                              from sp in session.SessionPresenters
                              where sp.Presenter.SiteUser != null
                              where sp.Presenter.SiteUser.UserIdentityProvider == identityProvider
                              where sp.Presenter.SiteUser.UserIdentityClaimType == claimType
                              where sp.Presenter.SiteUser.UserIdentityClaim == claim
                              select sp.Presenter
                            ).FirstOrDefault();
                    }
                }
            }
            return sessionPresenterMatchingUser;
        }

        protected void RemoveLocalClaims(SSP.IPrincipal principal)
        {
            MIC.IClaimsPrincipal claimsPrincipal = principal as MIC.IClaimsPrincipal;
            if (claimsPrincipal != null)
            {
                LocalClaimsManager.RemoveLocalClaims(claimsPrincipal);
            }
        }
#endif
        #endregion //ClaimsAuth

#if USE_MEMBERSHIP

        protected Presenter GetSessionPresenterMatchingUser(SSP.IPrincipal principal, Session session)
        {
            Presenter sessionPresenterMatchingUser = null;
            if (UserIsAuthenticated(principal) && (session != null) && (session.Id != 0) && !string.IsNullOrWhiteSpace(principal.Identity.Name))
            {
                sessionPresenterMatchingUser =
                    (
                      from sp in session.SessionPresenters
                      where sp.Presenter.SiteUser != null
                      where sp.Presenter.SiteUser.UserIdentityProvider == CodeCampDataRepository.IdentityProviders.CodeCamp
                      where sp.Presenter.SiteUser.UserIdentityClaimType == CodeCampDataRepository.ClaimTypes.username
                      where sp.Presenter.SiteUser.UserIdentityClaim == principal.Identity.Name
                      select sp.Presenter
                    ).FirstOrDefault();
            }
            return sessionPresenterMatchingUser;
        }
        
        protected bool UserMatchesSiteUser(SSP.IPrincipal principal, SiteUser siteUser)
        {
            if (UserIsAuthenticated(principal) && (siteUser != null) && (siteUser.Id != 0))
            {
                string identityProvider = CodeCampDataRepository.IdentityProviders.CodeCamp;
                string claimType = CodeCampDataRepository.ClaimTypes.username;
                string claim = principal.Identity.Name;
                if (!string.IsNullOrWhiteSpace(identityProvider) && !string.IsNullOrWhiteSpace(claimType)
                    && !string.IsNullOrWhiteSpace(claim))
                {
                    if (identityProvider.Equals(siteUser.UserIdentityProvider, StringComparison.InvariantCultureIgnoreCase)
                        && claimType.Equals(siteUser.UserIdentityClaimType, StringComparison.InvariantCultureIgnoreCase)
                        && claim.Equals(siteUser.UserIdentityClaim, StringComparison.InvariantCultureIgnoreCase))
                    {
                        return true;
                    }
                }
            }
            return false;
        }
#endif


        protected bool UserIsAuthenticated(SSP.IPrincipal principal)
        {
            return ((principal != null) && (principal.Identity != null) && principal.Identity.IsAuthenticated);
        }

        protected bool AuthorizedUserHasUnconnectedPresenterProfile(int eventId, SiteUser siteUser,
            CodeCampDataRepository ccdr)
        {
            if (siteUser != null)
            {
                if (!string.IsNullOrWhiteSpace(siteUser.EmailAddress))
                {
                    int presenterId = ccdr.GetDisconnectedPresenterId(eventId, siteUser.EmailAddress);
                    return (presenterId != 0);
                }
            }
            return false;
        }

        protected SiteUser GetSiteUser(CodeCampDataRepository ccdr, System.Security.Principal.IPrincipal principal)
        {
            return GetSiteUser(ccdr, principal, false);
        }

        protected SiteUser GetSiteUser(CodeCampDataRepository ccdr, System.Security.Principal.IPrincipal principal, bool userIsOnline)
        {
            SiteUser siteUser = null;
            if (UserIsAuthenticated(principal))
            {
#if USE_WIF
                bool principalHasIdentityProviderClaim;
                siteUser = GetSiteUser(ccdr, principal, userIsOnline, false, out principalHasIdentityProviderClaim);
#endif
#if USE_MEMBERSHIP
                siteUser = ccdr.GetSiteUser(CodeCampDataRepository.IdentityProviders.CodeCamp,
                                CodeCampDataRepository.ClaimTypes.username,
                                principal.Identity.Name,
                                userIsOnline);
#endif
            }
            return siteUser;
        }

#if USE_MEMBERSHIP
        protected SiteUser GetSiteUser(CodeCampDataRepository ccdr, string userName, bool userIsOnline, bool atLogin)
        {
            SiteUser siteUser = ccdr.GetSiteUser(CodeCampDataRepository.IdentityProviders.CodeCamp,
                            CodeCampDataRepository.ClaimTypes.username,
                            userName,
                            userIsOnline,
                            atLogin);
            return siteUser;
        }
#endif

        protected Presenter SiteUserPresenter(SiteUser siteUser, int eventId)
        {
            Presenter presenter = siteUser.Presenters.Where(p => p.EventId == eventId).FirstOrDefault();
            return presenter;
        }

        protected string LogName(SiteUser siteUser)
        {
            return SiteUserNameAndId(siteUser, 115);
        }

        protected string UpdateUser(SiteUser siteUser)
        {
            return SiteUserNameAndId(siteUser, 90);
        }

        protected string SiteUserNameAndId(SiteUser siteUser, int nameMaxLen)
        {
            string fullName = string.Concat(siteUser.FirstName, " ", siteUser.LastName).Trim().TruncateWithElipses(nameMaxLen);
            return string.Format("{0} {1}", fullName, siteUser.Id);
        }

        protected void SetSharedEventProperties(Event ccEvent, SharedViewModel viewModel, CodeCampDataRepository ccdr)
        {
            SetSharedEventProperties(ccEvent, viewModel, ccdr, false, false);
        }

        protected void SetSharedEventProperties(Event ccEvent, SharedViewModel viewModel, CodeCampDataRepository ccdr,
            bool userIsOnline)
        {
            SetSharedEventProperties(ccEvent, viewModel, ccdr, userIsOnline, false);
        }

        protected void SetSharedEventProperties(Event ccEvent, SharedViewModel viewModel, CodeCampDataRepository ccdr,
                            bool userIsOnline, bool atLogin)
        {
            viewModel.DefaultEventShortName = DefaultEventShortName;
            viewModel.EventShortName = ccEvent.ShortName;
            viewModel.EventDisplayName = ccEvent.DisplayName;
            if (viewModel.DefaultEventShortName == ccEvent.ShortName)
            {
                viewModel.DefaultEventDisplayName = ccEvent.DisplayName;
                viewModel.EventIsPublic = true;
            }
            else
            {
                viewModel.DefaultEventDisplayName = ccdr.GetEventDisplayName(DefaultEventShortName);
                viewModel.EventIsPublic = ccEvent.EventIsPublic;
            }
            //TODO: Revisit this when further work is done on schedule
            if (viewModel.EventIsPublic &&
                (ccEvent.ScheduleIsPublic || (ccEvent.EventStartDate < DateTime.Now)))
            {
                viewModel.PresentersArePublic = true;
            }
            else
            {
                viewModel.PresentersArePublic = false;
            }
            viewModel.AgendaIsPublic = ccEvent.AgendaIsPublic;
            viewModel.ScheduleIsPublic = ccEvent.ScheduleIsPublic;
            viewModel.ScheduleVisibleForPresenter = (ccEvent.ScheduleVisibleToPresenters && User.IsInRole(CCRoles.RoleNames.Presenter));
            if (User.IsInRole(CCRoles.RoleNames.BigCheeze) || User.IsInRole(CCRoles.RoleNames.EventContentEditor)
                || User.IsInRole(CCRoles.RoleNames.EventTrackLead))
            {
                viewModel.ScheduleInsider = true;
            }
            viewModel.EventStartDate = ccEvent.EventStartDate;
            viewModel.RegistrationUrl = ccEvent.RegistrationUrl.Trim();
            viewModel.SchedulePdfUrl = ccEvent.SchedulePdfUrl;
            viewModel.SubmissionsOpen = (ccEvent.SessionSubmissionsOpen < DateTime.Now)
                && (DateTime.Now < ccEvent.SessionSubmissionsClose);
            viewModel.SubmissionsCloseDate = ccEvent.SessionSubmissionsClose;
            viewModel.SubmissionsOpenDate = ccEvent.SessionSubmissionsOpen;

            //int presenterId = ccdr.GetPresenterId(ccEvent.Id, this.User.Identity.Name);
            
            //Allow presenter to create an login
            viewModel.PresenterLoginCreationAllowed = (viewModel.SubmissionsOpen || (viewModel.EventShortName == viewModel.DefaultEventShortName));
            //Allow presenter to create a profile
            viewModel.PresenterProfileCreationAllowed = viewModel.SubmissionsOpen;

            string partialName = string.Format("Partial/{0}Directions", ccEvent.ShortName);
            ViewEngineResult partial = ViewEngines.Engines.FindView(this.ControllerContext, partialName, null);
            if ((partial != null) && (partial.View != null))
                viewModel.ShowAboutDirections = true;

            SiteUser siteUser = null;
            if (UserIsAuthenticated(this.User))
            {
                bool presenterHasIdentityProviderClaim;
                siteUser = GetSiteUser(ccdr, this.User, userIsOnline, atLogin, out presenterHasIdentityProviderClaim);
                if (siteUser == null)
                {
#if USE_WIF
                    int claimCount;
                    string firstName, lastName;
                    GetNameClaim(this.User, CodeCampDataRepository.ClaimTypes.name_2005, out claimCount, out firstName, out lastName);
                    if (!string.IsNullOrWhiteSpace(firstName))
                    {
                        if (!string.IsNullOrWhiteSpace(lastName))
                            viewModel.FirstNamePlusLastInitial = string.Concat(firstName, " ", lastName.Substring(0, 1)).Trim();
                        else
                            viewModel.FirstNamePlusLastInitial = firstName;
                    }
                    if (string.IsNullOrWhiteSpace(viewModel.FirstNamePlusLastInitial))
                        viewModel.FirstNamePlusLastInitial = "new user";
#endif
#if USE_MEMBERSHIP
                    if (!string.IsNullOrWhiteSpace(this.User.Identity.Name))
                        viewModel.FirstNamePlusLastInitial = this.User.Identity.Name;
                    else
                        viewModel.FirstNamePlusLastInitial = "new user";
#endif
                }
                else
                {
                    this.SiteUserId = siteUser.Id;
                    viewModel.SiteUserId = siteUser.Id;
                    viewModel.FirstNamePlusLastInitial = string.Concat(siteUser.FirstName, " ", siteUser.LastName.Substring(0, 1)).Trim();
                    Nullable<int> presenterId = GetPresenterId(ccEvent.Id, siteUser);
                    viewModel.UserIsEventPresenter = presenterId.HasValue;
                    if (!presenterId.HasValue)
                    {
                        //Logged in site user is not a presenter for this event
                        if (!ccEvent.EventIsPublic)
                        {
                            //if SiteUser is allowed access to a non-public event, they are allowed to create a presenter profile
                            if (ccdr.SiteUserIsInRole(siteUser.Id, ccEvent.NonPublicEventPreviewRole))
                            {
                                viewModel.PresenterProfileCreationAllowed = true;
                            }
                        }
                        else if (ccEvent.DisconnectedPresenterProfileConnectionAllowed)
                        {
                            //This event allows disconnected presenter profiles to be reconnected
                            if (AuthorizedUserHasUnconnectedPresenterProfile(ccEvent.Id, siteUser, ccdr))
                            {
                                viewModel.PresenterProfileCreationAllowed = true;
                            }
                        }
                    }
                    else
                    {
                        //Site user already has presenter profile, so creation not allowed
                        viewModel.PresenterProfileCreationAllowed = false;
                    }
                }
            }
            SetLoggerThreadContextData(siteUser);
        }

        protected void SetSharedViewBagProperties(Event ccEvent)
        {
            ViewBag.RegistrationUrl = ccEvent.RegistrationUrl.Trim();
            ViewBag.DisplayName = ccEvent.DisplayName;
        }


        protected Presenter GetPresenter(int eventId, SiteUser siteUser)
        {
            Presenter presenter = null;
            if (siteUser != null)
            {
                presenter = siteUser.Presenters.Where(p => p.EventId == eventId).FirstOrDefault();
            }
            return presenter;
        }

        protected Nullable<int> GetPresenterId(int eventId, SiteUser siteUser)
        {
            Nullable<int> presenterId = null;
            if (siteUser != null)
            {
                presenterId = siteUser.Presenters.Where(p => p.EventId == eventId).Select(p => p.Id).FirstOrDefault();
                if (presenterId.HasValue && presenterId.Value == 0)
                    presenterId = null;
            }
            return presenterId;
        }

#if USE_WIF

        protected SiteUser FillViewModelFromDb(CodeCampDataRepository ccdr,
            Event ccEvent,
            SSP.IPrincipal principal,
            bool userIsOnline,
            CCM.UserRegisterModel model,
            out bool principalHasIdentityProviderClaim)
        {
            SiteUser siteUser = GetSiteUser(ccdr, principal, userIsOnline, false, out principalHasIdentityProviderClaim);
            if (siteUser != null)
            {
                SetSharedEventProperties(ccEvent, model, ccdr, userIsOnline);
                SiteUserId = siteUser.Id;
                model.FirstName = siteUser.FirstName;
                model.LastName = siteUser.LastName;
                model.Email = siteUser.EmailAddress;
                model.FirstNamePlusLastInitial = string.Concat(siteUser.FirstName, " ", siteUser.LastName.Substring(0, 1)).Trim();
            }
            return siteUser;
        }

        protected void FillViewModelFromDbOrClaims(CodeCampDataRepository ccdr,
            Event ccEvent,
            SSP.IPrincipal principal,
            bool userIsOnline,
            CCM.UserRegisterModel model,
            out string identityProvider)
        {
            identityProvider = null;
            bool principalHasIdentityProviderClaim;
            SiteUser siteUser = FillViewModelFromDb(ccdr, ccEvent, principal, userIsOnline, model, out principalHasIdentityProviderClaim);
            if (siteUser == null)
            {
                model.RegisteredSiteUserId = 0;
                int claimCount;
                MIC.Claim providerClaim = GetFirstClaim(principal, CodeCampDataRepository.ClaimTypes.identityprovider_2010, out claimCount);
                if (providerClaim != null)
                    identityProvider = providerClaim.Value;
                string firstName, lastName;
                GetNameClaim(principal, CodeCampDataRepository.ClaimTypes.name_2005, out claimCount, out firstName, out lastName);
                model.FirstName = firstName;
                model.LastName = lastName;
                model.Email = GetFirstClaimValue(principal, CodeCampDataRepository.ClaimTypes.emailaddress_2005, out claimCount);
                if (!string.IsNullOrWhiteSpace(firstName))
                {
                    if (!string.IsNullOrWhiteSpace(lastName))
                    {
                        model.FirstNamePlusLastInitial = firstName;
                    }
                    else
                    {
                        model.FirstNamePlusLastInitial = string.Concat(firstName, " ", lastName.Substring(0, 1)).Trim();
                    }
                }
            }
        }

        protected SiteUser FillNewSiteUser(CCM.UserRegisterModel model, SSP.IPrincipal principal,
            out bool newSiteUserIsValid)
        {
            newSiteUserIsValid = false;
            SiteUser siteUser = new SiteUser
            {
                EmailAddress = model.Email,
                FirstName = model.FirstName,
                LastName = model.LastName
            };

            MIC.ClaimsIdentity claimsIdent = null;
            MIC.ClaimsPrincipal claimsPrincipal = principal as MIC.ClaimsPrincipal;
            if (claimsPrincipal != null)
            {
                claimsIdent = claimsPrincipal.Identity as MIC.ClaimsIdentity;
            }
            if (claimsIdent == null)
            {
                ModelState.AddModelError("", "Internal data error (1).  Try closing all browsers and starting again.");
                Logger.Error("Failed to get ClaimsPrincipal.");
            }
            else
            {
                int claimCount;
                string claimType = CodeCampDataRepository.ClaimTypes.nameidentifier_2005;
                MIC.Claim nameidClaim = null;
                nameidClaim = GetFirstClaim(claimsIdent.Claims, CodeCampDataRepository.ClaimTypes.nameidentifier_2005, out claimCount);
                if (nameidClaim == null)
                {
                    Logger.WarnFormat("Join POST failed to get claim \"{2}\" for (authenticated={0}) user \"{1}\".",
                        this.User.Identity.IsAuthenticated,
                        this.User.Identity.Name,
                        claimType);
                    ModelState.AddModelError("", "Internal data error (3).  Try closing all browsers and starting again.");
                }
                else
                {
                    siteUser.UserIdentityClaimType = nameidClaim.ClaimType;
                    siteUser.UserIdentityIssuer = nameidClaim.OriginalIssuer;
                    siteUser.UserIdentityClaim = nameidClaim.Value;

                    claimType = CodeCampDataRepository.ClaimTypes.identityprovider_2010;
                    MIC.Claim providerClaim = GetFirstClaim(claimsIdent.Claims, claimType, out claimCount);
                    if (providerClaim == null)
                    {
                        Logger.WarnFormat("Join POST failed to get claim \"{2}\" for (authenticated={0}) user \"{1}\".",
                            this.User.Identity.IsAuthenticated,
                            this.User.Identity.Name,
                            claimType);
                        ModelState.AddModelError("", "Internal data error (3).  Try closing all browsers and starting again.");
                    }
                    else
                    {
                        siteUser.UserIdentityProvider = providerClaim.Value;

                        claimType = CodeCampDataRepository.ClaimTypes.emailaddress_2005;
                        MIC.Claim emailClaim = GetFirstClaim(claimsIdent.Claims, claimType, out claimCount);
                        if (emailClaim != null)
                        {
                            siteUser.UserClaimEmailAddress = emailClaim.Value;
                        }

                        if (!string.IsNullOrWhiteSpace(siteUser.UserClaimEmailAddress))
                            siteUser.CreatedBy = siteUser.UserClaimEmailAddress;
                        else
                            siteUser.CreatedBy = siteUser.EmailAddress;

                        newSiteUserIsValid = true;
                    }
                }
            }
            return siteUser;
        }
#endif

        protected SiteUser GetSiteUser(CodeCampDataRepository ccdr,
            SSP.IPrincipal principal,
            bool userIsOnline,
            bool atLogin,
            out bool principalHasIdentityProviderClaim)
        {
            principalHasIdentityProviderClaim = false;
            SiteUser siteUser = null;
            MIC.ClaimsPrincipal claimsPrincipal = principal as MIC.ClaimsPrincipal;
            if (claimsPrincipal != null)
            {
                MIC.ClaimsIdentity claimsIdent = claimsPrincipal.Identity as MIC.ClaimsIdentity;
                if (claimsIdent != null)
                {
                    int claimCount;
                    string identityProvider = null;
                    string claimType = null;
                    string claim = null;

                    MIC.Claim providerClaim = GetFirstClaim(claimsIdent.Claims, CodeCampDataRepository.ClaimTypes.identityprovider_2010, out claimCount);
                    MIC.Claim identityClaim = GetFirstClaim(claimsIdent.Claims, CodeCampDataRepository.ClaimTypes.nameidentifier_2005, out claimCount);
                    if ((providerClaim != null) && (identityClaim != null))
                    {
                        principalHasIdentityProviderClaim = true;
                        identityProvider = providerClaim.Value;
                        claimType = identityClaim.ClaimType;
                        claim = identityClaim.Value;
                    }
                    else
                    {
                        MIC.Claim nameClaim = ControllerBase.GetFirstClaim(claimsIdent.Claims, CodeCampDataRepository.ClaimTypes.name_2005, out claimCount);
                        if (nameClaim != null)
                        {
                            identityProvider = CodeCampDataRepository.IdentityProviders.CodeCamp;
                            claimType = CodeCampDataRepository.ClaimTypes.username;
                            claim = nameClaim.Value;
                        }
                    }

                    if (!string.IsNullOrWhiteSpace(identityProvider) && !string.IsNullOrWhiteSpace(claimType) && !string.IsNullOrWhiteSpace(claim))
                    {
                        siteUser = ccdr.GetSiteUser(identityProvider, claimType, claim, userIsOnline, atLogin);
                    }
                }
            }
            return siteUser;
        }

#if false

        protected SiteUser GetSiteUser(CodeCampDataRepository ccdr, string membershipUsername,
            bool userIsOnline)
        {
            SiteUser siteUser
                = ccdr.GetSiteUser(CodeCampDataRepository.IdentityProviders.CodeCamp,
                                    CodeCampDataRepository.ClaimTypes.username,
                                    membershipUsername,
                                    userIsOnline);
            return siteUser;
        }

        protected SiteUser GetSiteUserAtLogon(CodeCampDataRepository ccdr, string membershipUsername)
        {
            SiteUser siteUser
                = ccdr.GetSiteUserAtLogon(CodeCampDataRepository.IdentityProviders.CodeCamp,
                                    CodeCampDataRepository.ClaimTypes.username,
                                    membershipUsername);
            return siteUser;
        }
#endif

#if false
        protected SiteUser GetSiteUser(CodeCampDataRepository ccdr,
            SSP.IPrincipal principal,
            bool userIsOnline,
            bool atLogin,
            out bool principalHasIdentityProviderClaim)
        {
            principalHasIdentityProviderClaim = false;
            SiteUser siteUser = null;
            if (UserIsAuthenticated(principal))
            {
                siteUser = ccdr.GetSiteUser(CodeCampDataRepository.IdentityProviders.CodeCamp,
                                    CodeCampDataRepository.ClaimTypes.username,
                                    principal.Identity.Name,
                                    userIsOnline,
                                    atLogin);
            }
            return siteUser;
        }

#endif

        protected List<string> GetSiteUserRoles(CodeCampDataRepository ccdr, int siteUserId, int eventId)
        {
            return ccdr.GetSiteUserRoles(siteUserId, eventId);
        }

        protected ActionResult Test(string eventName, string exLogControllerAndAction,
            System.Text.StringBuilder testMsg)
        {
            using (var ccdr = new CodeCampDataRepository())
            {
                var ccEvent = EventsHelper.GetEvent(ccdr, eventName, DefaultEventShortName, this.User);
                return Test(eventName, exLogControllerAndAction, ccdr, ccEvent, testMsg);
            }
        }

        protected ActionResult Test(string eventName, string exLogControllerAndAction,
            CodeCampDataRepository repository,
            Event ccEvent,
            System.Text.StringBuilder testMsg)
        {
            SetLoggerThreadContextData();
            try
            {
                SetSharedViewBagProperties(ccEvent);
                TestViewModel model = new TestViewModel();

                testMsg.AppendFormat("Event Id={0}, ShortName=\"{1}\"",
                    ccEvent.Id,
                    ccEvent.ShortName);

                model.TestMsg = testMsg.ToString();
                SetSharedEventProperties(ccEvent, model, repository);
                return View("Test", model);
            }
            catch (Exception ex)
            {
                TempData.Add(TempDataKeys.ErrorMessage, "Error saving new event.");
                LogException("Presenters/Test1", ex);
                return RedirectToAction("Index", "Errors");
            }
            finally
            {
                testMsg.Insert(0, Environment.NewLine);
                testMsg.Insert(0, "Test1");
                Logger.Debug(testMsg.ToString());
            }
        }

        protected bool SendEmail(SNM.SmtpClient mailClient,
            SNM.MailAddress fromAddress,
            SNM.MailAddress toAddress,
            string subject,
            System.Text.StringBuilder msgBody,
            string controllerAndActionForLogMsg,
            out bool invalidToEmailAddress)
        {
            invalidToEmailAddress = false;
            try
            {
                SNM.MailMessage message = new SNM.MailMessage(fromAddress, toAddress);
                message.IsBodyHtml = false;
                message.Subject = !string.IsNullOrWhiteSpace(subject) ? subject : "Account Information you requested";
                message.Body = msgBody.ToString();
                mailClient.Send(message);
                return true;
            }
            catch (SNM.SmtpFailedRecipientException ex)
            {
                LogException(controllerAndActionForLogMsg, ex);
                invalidToEmailAddress = true;
                return false;
            }
            catch (SNM.SmtpException ex)
            {
                LogException(controllerAndActionForLogMsg, ex);
                return false;
            }
        }

        protected string SessionTitle(CodeCamp.Model.Session session)
        {
            CodeCamp.Model.Session.SessionStatus status = CodeCamp.Model.Session.GetSessionStatus(session.SessionStatusId);
            switch (status)
            {
                case Model.Session.SessionStatus.Submitted:
                case Model.Session.SessionStatus.Selected:
                    return session.Title;

                case Model.Session.SessionStatus.LateCancel:
                    return string.Concat(session.Title, " CANCELLED");

                case Model.Session.SessionStatus.Undefined:
                    if (session.SessionStatusId == 0)
                        return string.Format("[{0}] {1}", status, session.Title);
                    else
                        return string.Format("[Status {0}] {1}", session.SessionStatusId, session.Title);

                case Model.Session.SessionStatus.Cancelled:
                case Model.Session.SessionStatus.Declined:
                default:
                    return string.Format("[{0}] {1}", status, session.Title);
            }
        }

        protected bool SessionIsPublic(CodeCamp.Model.Session session)
        {
            CodeCamp.Model.Session.SessionStatus status = CodeCamp.Model.Session.GetSessionStatus(session.SessionStatusId);
            switch (status)
            {
                case Model.Session.SessionStatus.Submitted:
                case Model.Session.SessionStatus.Selected:
                case Model.Session.SessionStatus.LateCancel:
                    return true;

                default:
                    return false;
            }
        }

    }
}